﻿//***********************************************************************************************************************
//
//文件名(File Name):     IminectPlayerInfo .cs
//
//功能描述(Description):    玩家体感数据存储类
//
//作者(Author):		郭佳
//
//日期(Create Date):	
//
//修改记录(Revision History):
//			R1：
//				修改作者:
//				修改日期:
//				修改理由:				
//
//***********************************************************************************************************************

using UnityEngine;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using IMIForUnity;

namespace IMIForUnity
{

    public class ImiPlayerInfo : IPlayerInfo
    {
        public int userId;
        public bool playerTracked;
        public Vector3 playerPosition;
        public Vector3 playerGround;
        public Vector3[] playerLimbsAngular;
        internal ImiSkeleton[] skeletons;
        public Vector3[] normalizedSkeletonPos;
        public Vector3[] playerJointsPos;
        public Vector3[] playerJointsSpeed;
        public Quaternion[] playerJointsOri;
        public bool[] playerJointsTracked;
        public bool isOrigFixRec = false;
        internal ImiSkeletonTrackingState trackingState;
        public Dictionary<System.Type,ImiGesture> playerGestures;

        //玩家固定的位置信息
        public float fixPosZ;
        //玩家直立的时候臀部高度
        public float fixHipPosY;
        //玩家直立的时候左膝高度
        public float fixLeftKneePosY;
        //玩家直立的时候右膝高度
        public float fixRightKneePosY;

        public long fixFrameCount;

        public ImiPlayerInfo()
        {
            this.userId = 0;
            this.playerTracked = false;
            this.playerPosition = new Vector3();

            this.isOrigFixRec = false;
            this.playerLimbsAngular = new Vector3[(int)Limb.Count];
            for (int i = 0; i < (int)Limb.Count; i++)
            {
                playerLimbsAngular[i] = new Vector3(-1.0f, -1.0f, -1.0f);
            }
            int skeletonCount = (int)ImiSkeleton.Index.COUNT;
            normalizedSkeletonPos = new Vector3[skeletonCount];
            playerJointsPos = new Vector3[skeletonCount];
            playerJointsSpeed = new Vector3[skeletonCount];
            playerJointsTracked = new bool[skeletonCount];
            playerJointsOri = new Quaternion[skeletonCount];

            skeletons = new ImiSkeleton[skeletonCount];
            for(int i = 0; i< skeletonCount; i++)
            {
                skeletons[i].id = (ImiSkeleton.Index)i;
            }
 
            playerGestures = new Dictionary<Type, ImiGesture>();

        }

        //public void ResetFixValue()
        //{
        //    isOrigFixRec = false;
        //    fixPosZ = GetPlayerPosition().z;
        //    fixHipPosY = GetSkeletons()[ImiGesture.hipCenterIndex].position.y;
        //    fixLeftKneePosY = GetSkeletons()[ImiGesture.leftKneeIndex].position.y;
        //    fixRightKneePosY = GetSkeletons()[ImiGesture.rightKneeIndex].position.y;
        //    fixFrameCount = 0;
        //}

        public ImiSkeleton[] GetSkeletons()
        {
            return this.skeletons;
        }

        public Vector3[] GetNormalizedSkeletonPos()
        {
            ImiSkeleton centerSkeleton = skeletons[(int)ImiSkeleton.Index.HIP_CENTER];

            Vector3 depthCenter = Utils.ConvertSkeletonPointToDepthPoint(playerPosition);
            float baseLine = 2.0f;
            float ratio = baseLine / playerPosition.z;
            if (ratio <= 0)
            {
                ratio = 1;
            }
            int centerx =  320;
            int centery =  240;
            int offsetX = centerx - (int)depthCenter.x;
            int offsetY = centery - (int)depthCenter.y;


            Vector3 tempDepth;
            for (int i=0; i < (int)ImiSkeleton.Index.COUNT; i++)
            {
                //skeleton to depth point
                tempDepth = Utils.ConvertSkeletonPointToDepthPoint(skeletons[i].position);

                //depth point translate and scale
                tempDepth.x += offsetX;
                tempDepth.y += offsetY;
                tempDepth.x = centerx + (tempDepth.x - centerx) / ratio;
                tempDepth.y = centery + (tempDepth.y - centery) / ratio;
                tempDepth.z = tempDepth.z / ratio;

                //new depth point to skeleton point
                normalizedSkeletonPos[i] = Utils.ConvertDepthPointToSkeletonPoint(tempDepth);
            }           

            return normalizedSkeletonPos;
        }

        public bool[] GetPlayerJointsTracked()
        {
            //TODO this method needs to cache the result to avoid recaculate everytime
            for (int i = 0; i < skeletons.Length; i++)
            {
                playerJointsTracked[i] = skeletons[i].isTracked;
            }
            return playerJointsTracked;
        }

        public Vector3[] GetPlayerJointsPos()
        {
            for (int i = 0; i < skeletons.Length; i++)
            {
                playerJointsPos[i] = skeletons[i].position;
            }
            return playerJointsPos;
        }

        public Vector3[] GetPlayerJointsSpeed()
        {
            for (int i = 0; i < skeletons.Length; i++)
            {
                playerJointsSpeed[i] = skeletons[i].speed;
            }
            return playerJointsSpeed;
        }

        internal void Update(ImiWrapper.ImiSkeletonFrame skeletonFrame)
        {
            //TODO
        }

        internal void SetUserId(int id)
        {
            this.userId = id;
        }

        internal void SetPlayerLimbsAngular(int limb, Vector3 angular)
        {
            this.playerLimbsAngular[limb] = angular;
        }

        public Vector3[] GetPlayerLimbsAngular()
        {
            return this.playerLimbsAngular;
        }


        internal void SetPlayerTracked(bool tracked)
        {
            this.playerTracked = tracked;
        }

        internal void SetPlayerPosition(float x, float y, float z)
        {
            this.playerPosition.x = x;
            this.playerPosition.y = y;
            this.playerPosition.z = z;
        }

        public Quaternion[] GetPlayerJointsOri()
        {
            for (int i = 0; i < skeletons.Length; i++)
            {
                playerJointsOri[i] = skeletons[i].orientation;
            }
            return playerJointsOri;
        }

        public int GetUserId()
        {
            return this.userId;
        }

        public bool GetPlayerTracked()
        {
            return this.playerTracked;
        }
        
        public Vector3 GetPlayerPosition()
        {
            return this.playerPosition;
        }

    }

}